package com.ylr.send.framework.service.impl;

import com.ylr.redis.framework.service.RedissonService;
import com.ylr.send.common.dto.SmsTemplateDto;
import com.ylr.send.common.dto.SmsTemplatePageEnumDto;
import com.ylr.send.common.vo.SmsTemplateFormVo;
import com.ylr.send.common.vo.SmsTemplateVo;
import com.ylr.send.framework.service.SmsTemplateFlowService;
import com.ylr.send.framework.service.SmsTemplateService;
import com.ylr.base.common.constant.RedisConstant;
import com.ylr.base.common.dto.PageDto;
import com.ylr.base.common.enums.CommonEnum;
import com.ylr.base.common.enums.ResultEnum;
import com.ylr.send.common.enums.SmsCodeEnum;
import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.po.user.UserPo;
import com.ylr.base.common.tool.PageQuery;
import com.ylr.base.common.utils.UserUtils;
import com.ylr.base.common.vo.UpdateStatusVo;
import com.ylr.base.framework.service.SnowflakeService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ylr.send.common.constant.SendConstant;
import com.ylr.send.common.enums.SendResultEnum;
import com.ylr.send.framework.mapper.SmsTemplateMapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ylr.send.framework.entity.SmsTemplateEntity;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-06-14 21:23:54
 * className: SmsTemplateServiceImpl
 * version: 1.0
 * description:
 */
@Service("smsTemplateService")
@AllArgsConstructor
public class SmsTemplateServiceImpl extends ServiceImpl<SmsTemplateMapper, SmsTemplateEntity> implements SmsTemplateService {

    private static final Logger log = LoggerFactory.getLogger(SmsTemplateServiceImpl.class);

    private final SmsTemplateFlowService smsTemplateFlowService;

    private final SnowflakeService snowflakeService;

    private final RedissonService redissonService;

    @Transactional
    @Override
    public void saveSmsTemplate(SmsTemplateVo smsTemplateVo) {

        String lockKey = RedisConstant.LOCK_PREFIX + SendConstant.SMS_TEMPLATE + smsTemplateVo.getCode();
        Runnable runnable = () -> {
            // 获取正在保存短信模板的用户
            UserPo userPo = UserUtils.getUser();
            Date date = new Date();

            // 1、查询短信模板是否存在
            SmsTemplateEntity smsTemplate = baseMapper.selectByCode(smsTemplateVo.getCode());
            if (Objects.isNull(smsTemplate)) {
                // 2、新短信模板
                smsTemplate = this.newSmsTemplate(smsTemplateVo, userPo, date);

                baseMapper.insert(smsTemplate);
                log.info("保存短信模板完成");
            } else {
                if (CommonEnum.DELETE_NO.getValue().equals(smsTemplate.getDeleteStatus())) {
                    log.info("短信模板已存在，新增失败");
                    throw new YlrException(ResultEnum.REFRESH);
                }
                // 2、修改数据
                smsTemplate.setChannel(smsTemplateVo.getChannel())
                        .setCode(smsTemplateVo.getCode())
                        .setTname(smsTemplateVo.getTname())
                        .setContent(smsTemplateVo.getContent())
                        .setParams(smsTemplateVo.getParams())
                        .setVersion(smsTemplate.getVersion() + 1)
                        .setStatus(CommonEnum.STATUS_USE.getValue())
                        .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                        .setUpdateTime(date)
                        .setUpdateUser(userPo.getUsername())
                        .setUpdateUserId(userPo.getId());
                // 修改数据
                int count = baseMapper.updateById(smsTemplate);
                log.info("修改短信模板完成。count={}", count);
            }

            // 3、增加短信模板流水
            smsTemplateFlowService.saveSmsTemplateFlow(smsTemplate.getId(), smsTemplateVo.getChannel(), smsTemplateVo.getCode(),
                    smsTemplateVo.getTname(), smsTemplateVo.getContent(), smsTemplateVo.getParams(), smsTemplate.getVersion());
        };
        // 加锁运行
        redissonService.tryLockRun(lockKey, runnable, ResultEnum.TRY_LOCK_FAIL);
    }

    @Override
    public PageDto<SmsTemplateDto> pageSmsTemplateList(SmsTemplateFormVo smsTemplateFormVo) {
        // mp分页对象
        Page<SmsTemplateEntity> page = PageQuery.initPage(smsTemplateFormVo);

        LambdaQueryWrapper<SmsTemplateEntity> smsTemplateLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        smsTemplateLambdaQueryWrapper.select(SmsTemplateEntity::getId, SmsTemplateEntity::getChannel, SmsTemplateEntity::getCode,
                SmsTemplateEntity::getTname, SmsTemplateEntity::getContent, SmsTemplateEntity::getParams, SmsTemplateEntity::getVersion,
                SmsTemplateEntity::getStatus, SmsTemplateEntity::getUpdateTime, SmsTemplateEntity::getUpdateUser, SmsTemplateEntity::getCreateTime,
                SmsTemplateEntity::getCreateUser);
        // 匹配条件
        smsTemplateLambdaQueryWrapper.eq(Objects.nonNull(smsTemplateFormVo.getCode()), SmsTemplateEntity::getCode, smsTemplateFormVo.getCode())
                .eq(Objects.nonNull(smsTemplateFormVo.getChannel()), SmsTemplateEntity::getChannel, smsTemplateFormVo.getChannel())
                .like(StringUtils.isNotBlank(smsTemplateFormVo.getWord()), SmsTemplateEntity::getContent, smsTemplateFormVo.getWord())
                .eq(Objects.nonNull(smsTemplateFormVo.getStatus()), SmsTemplateEntity::getStatus, smsTemplateFormVo.getStatus())
                .eq(SmsTemplateEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 查询数据
        baseMapper.selectPage(page, smsTemplateLambdaQueryWrapper);

        List<SmsTemplateEntity> smsTemplateList = page.getRecords();
        long totalNum = page.getTotal();
        if (smsTemplateList.isEmpty()) {
            log.info("短信模板分页查询结果为空");
            return new PageDto<>(Collections.emptyList(), totalNum, smsTemplateFormVo.getPageNo(), smsTemplateFormVo.getPageSize());
        }
        // 数据封装
        List<SmsTemplateDto> smsTemplateDtoList = new ArrayList<>();
        for (SmsTemplateEntity smsTemplate : smsTemplateList) {
            smsTemplateDtoList.add(this.getSmsTemplateDto(smsTemplate));
        }
        return new PageDto<>(smsTemplateDtoList, totalNum, smsTemplateFormVo.getPageNo(), smsTemplateFormVo.getPageSize());
    }

    @Override
    public SmsTemplateDto getSmsTemplate(Long id) {
        // 查询数据
        SmsTemplateEntity smsTemplate = this.findSmsTemplate(id);

        return this.getSmsTemplateDto(smsTemplate);
    }

    @Override
    public SmsTemplateEntity getSmsTemplateByCode(String code) {
        SmsTemplateEntity smsTemplate = baseMapper.selectByCode(code);
        if (Objects.isNull(smsTemplate)) {
            log.info("短信模板不存在");
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
        if (CommonEnum.DELETE_YES.getValue().equals(smsTemplate.getDeleteStatus())) {
            log.info("短信模板已删除");
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
        if (CommonEnum.STATUS_DISABLE.getValue().equals(smsTemplate.getStatus())) {
            log.info("短信模板已禁用");
            throw new YlrException(SendResultEnum.SMS_TEMPLATE_DISABLE_FAIL);
        }
        return smsTemplate;
    }

    @Override
    public SmsTemplatePageEnumDto getPageEnum() {

        SmsTemplatePageEnumDto smsTemplatePageEnumDto = new SmsTemplatePageEnumDto();
        smsTemplatePageEnumDto.setCodeEnumList(SmsCodeEnum.getEnumList())
                .setStatusEnumList(CommonEnum.getStatusEnumList());
        return smsTemplatePageEnumDto;
    }

    @Override
    public void updateSmsTemplate(SmsTemplateVo smsTemplateVo) {
        String lockKey = RedisConstant.LOCK_PREFIX + SendConstant.SMS_TEMPLATE + smsTemplateVo.getCode();
        Runnable runnable = () -> {
            // 获取正在修改短信模板的用户
            UserPo userPo = UserUtils.getUser();
            Date date = new Date();

            // 1、查询短信模板
            SmsTemplateEntity smsTemplate = this.findSmsTemplate(smsTemplateVo.getId());
            if (!smsTemplateVo.getVersion().equals(smsTemplate.getVersion())) {
                log.info("短信模板已变更。oldVersion={} newVersion={}", smsTemplate.getVersion(), smsTemplateVo.getVersion());
                throw new YlrException(ResultEnum.REFRESH);
            }

            SmsTemplateEntity _smsTemplate = this.makeSmsTemplate(smsTemplateVo, userPo, date);

            // 2、修改数据
            baseMapper.updateById(_smsTemplate);
            log.info("修改短信模板完成");

            // 3、增加短信模板流水
            smsTemplateFlowService.saveSmsTemplateFlow(smsTemplateVo.getId(), smsTemplateVo.getChannel(), smsTemplateVo.getCode(),
                    smsTemplateVo.getTname(), smsTemplateVo.getContent(), smsTemplateVo.getParams(), _smsTemplate.getVersion());
        };
        // 加锁运行
        redissonService.tryLockRun(lockKey, runnable, ResultEnum.TRY_LOCK_FAIL);

    }

    @Override
    public void updateSmsTemplateStatus(UpdateStatusVo updateStatusVo) {
        // 获取正在修改短信模板状态的用户
        UserPo userPo = UserUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<SmsTemplateEntity> smsTemplateLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        smsTemplateLambdaUpdateWrapper.set(SmsTemplateEntity::getStatus, updateStatusVo.getStatus())
                .set(SmsTemplateEntity::getUpdateTime, date)
                .set(SmsTemplateEntity::getUpdateUser, userPo.getUsername())
                .set(SmsTemplateEntity::getUpdateUserId, userPo.getId());
        // 匹配条件
        smsTemplateLambdaUpdateWrapper.in(SmsTemplateEntity::getId, updateStatusVo.getIdList())
                .eq(SmsTemplateEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, smsTemplateLambdaUpdateWrapper);
        log.info("修改短信模板状态完成。count={}", count);
        if (count == 0) {
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
    }

    @Override
    public void deleteSmsTemplate(List<Long> idList) {
        // 获取正在删除短信模板的用户
        UserPo userPo = UserUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<SmsTemplateEntity> smsTemplateLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        smsTemplateLambdaUpdateWrapper.set(SmsTemplateEntity::getDeleteStatus, CommonEnum.DELETE_YES.getValue())
                .set(SmsTemplateEntity::getUpdateTime, date)
                .set(SmsTemplateEntity::getUpdateUser, userPo.getUsername())
                .set(SmsTemplateEntity::getUpdateUserId, userPo.getId());
        // 匹配条件
        smsTemplateLambdaUpdateWrapper.in(SmsTemplateEntity::getId, idList)
                .eq(SmsTemplateEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, smsTemplateLambdaUpdateWrapper);
        log.info("删除短信模板完成。count={}", count);
    }

    /**
     * 查询短信模板
     * @param id 主键
     * @return 短信模板对象
     */
    private SmsTemplateEntity findSmsTemplate(Long id) {
        SmsTemplateEntity smsTemplate = baseMapper.selectById(id);
        if (Objects.isNull(smsTemplate)) {
            log.info("短信模板不存在");
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
        if (CommonEnum.DELETE_YES.getValue().equals(smsTemplate.getDeleteStatus())) {
            log.info("短信模板已删除");
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
        return smsTemplate;
    }

    /**
     * 生成短信模板实体对象
     * @param smsTemplateVo 参数对象
     * @return 短信模板实体对象
     */
    private SmsTemplateEntity newSmsTemplate(SmsTemplateVo smsTemplateVo, UserPo userPo, Date date) {
        SmsTemplateEntity smsTemplate = new SmsTemplateEntity();
        smsTemplate.setId(snowflakeService.getId())
                .setChannel(smsTemplateVo.getChannel())
                .setCode(smsTemplateVo.getCode())
                .setTname(smsTemplateVo.getTname())
                .setContent(smsTemplateVo.getContent())
                .setParams(smsTemplateVo.getParams())
                .setVersion(smsTemplateVo.getVersion())
                .setStatus(CommonEnum.STATUS_USE.getValue())
                .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.DEFAULT_ID.getLongValue())
                .setCreateTime(date)
                .setCreateUser(userPo.getUsername())
                .setCreateUserId(userPo.getId());
        return smsTemplate;
    }

    /**
     * 短信模板实体对象封装
     * @param smsTemplate 短信模板实体对象
     * @return 封装结果
     */
    private SmsTemplateDto getSmsTemplateDto(SmsTemplateEntity smsTemplate) {
        SmsTemplateDto smsTemplateDto = new SmsTemplateDto();
        smsTemplateDto.setId(smsTemplate.getId().toString())
                .setChannel(smsTemplate.getChannel())
                .setCode(smsTemplate.getCode())
                .setTname(smsTemplate.getTname())
                .setContent(smsTemplate.getContent())
                .setParams(smsTemplate.getParams())
                .setVersion(smsTemplate.getVersion())
                .setStatus(smsTemplate.getStatus())
                .setUpdateTime(smsTemplate.getUpdateTime())
                .setUpdateUser(smsTemplate.getUpdateUser())
                .setCreateTime(smsTemplate.getCreateTime())
                .setCreateUser(smsTemplate.getCreateUser());
        return smsTemplateDto;
    }

    /**
     * 生成短信模板实体对象
     * @param smsTemplateVo 参数对象
     * @return 短信模板实体对象
     */
    private SmsTemplateEntity makeSmsTemplate(SmsTemplateVo smsTemplateVo, UserPo userPo, Date date) {
        SmsTemplateEntity smsTemplate = new SmsTemplateEntity();
        smsTemplate.setId(smsTemplateVo.getId())
                .setChannel(smsTemplateVo.getChannel())
                .setCode(smsTemplateVo.getCode())
                .setTname(smsTemplateVo.getTname())
                .setContent(smsTemplateVo.getContent())
                .setParams(smsTemplateVo.getParams())
                .setVersion(smsTemplateVo.getVersion() + 1)
                .setUpdateTime(date)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getId());
        return smsTemplate;
    }
}